home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Atari Mega Archive 1
/
Atari Mega Archive - Volume 1.iso
/
mint
/
editors
/
mntemacs.zoo
/
src
/
lread.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-12-02
|
32KB
|
1,315 lines
/* Lisp parsing and input streams.
Copyright (C) 1985, 1986, 1987 Free Software Foundation, Inc.
This file is part of GNU Emacs.
GNU Emacs is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option)
any later version.
GNU Emacs is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Emacs; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/file.h>
#undef NULL
#include "config.h"
#include "lisp.h"
/**
** (sjk)++ a simple prototype. :-)
**/
#ifdef atarist
static int read_escape();
#endif
#ifndef standalone
#include "buffer.h"
#include "paths.h"
#endif
#ifdef lint
#include <sys/inode.h>
#endif /* lint */
#ifndef X_OK
#define X_OK 01
#endif
Lisp_Object Qread_char, Qget_file_char, Qstandard_input;
Lisp_Object Qvariable_documentation, Vvalues, Vstandard_input;
/* non-zero if inside `load' */
int load_in_progress;
/* Search path for files to be loaded. */
Lisp_Object Vload_path;
/* File for get_file_char to read from. Use by load */
static FILE *instream;
/* When nonzero, read conses in pure space */
static int read_pure;
/* For use within read-from-string (this reader is non-reentrant!!) */
static int read_from_string_index;
static int read_from_string_limit;
/* Handle unreading and rereading of characters.
Write READCHAR to read a character, UNREAD(c) to unread c to be read again. */
static int unrch;
static int readchar (readcharfun)
Lisp_Object readcharfun;
{
Lisp_Object tem;
register struct buffer *inbuffer;
register int c, mpos;
if (unrch >= 0)
{
c = unrch;
unrch = -1;
return c;
}
if (XTYPE (readcharfun) == Lisp_Buffer)
{
inbuffer = XBUFFER (readcharfun);
if (BUF_PT (inbuffer) >= BUF_ZV (inbuffer))
return -1;
c = *(unsigned char *) BUF_CHAR_ADDRESS (inbuffer, BUF_PT (inbuffer));
SET_BUF_PT (inbuffer, BUF_PT (inbuffer) + 1);
return c;
}
if (XTYPE (readcharfun) == Lisp_Marker)
{
inbuffer = XMARKER (readcharfun)->buffer;
mpos = marker_position (readcharfun);
if (mpos > BUF_ZV (inbuffer) - 1)
return -1;
c = *(unsigned char *) BUF_CHAR_ADDRESS (inbuffer, mpos);
if (mpos != BUF_GPT (inbuffer))
XMARKER (readcharfun)->bufpos++;
else
Fset_marker (readcharfun, make_number (mpos + 1),
Fmarker_buffer (readcharfun));
return c;
}
if (EQ (readcharfun, Qget_file_char))
return getc (instream);
if (XTYPE (readcharfun) == Lisp_String)
{
register int c;
/* This used to be return of a conditional expression,
but that truncated -1 to a char on VMS. */
if (read_from_string_index < read_from_string_limit)
c = XSTRING (readcharfun)->data[read_from_string_index++];
else
c = -1;
return c;
}
tem = call0 (readcharfun);
if (NULL (tem))
return -1;
return XINT (tem);
}
#define READCHAR readchar(readcharfun)
#define UNREAD(c) (unrch = c)
static Lisp_Object read0 (), read1 (), read_list (), read_vector ();
/* get a character from the tty */
DEFUN ("read-char", Fread_char, Sread_char, 0, 0, 0,
"Read a character from the command input (keyboard or macro).\n\
It is returned as a number.")
()
{
register Lisp_Object val;
#ifndef standalone
XSET (val, Lisp_Int, read_command_char (0));
#else
XSET (val, Lisp_Int, getchar ());
#endif
return val;
}
DEFUN ("get-file-char", Fget_file_char, Sget_file_char, 0, 0, 0,
"Don't use this yourself.")
()
{
register Lisp_Object val;
XSET (val, Lisp_Int, getc (instream));
return val;
}
void readevalloop ();
static Lisp_Object load_unwind ();
DEFUN ("load", Fload, Sload, 1, 4, 0,
"Execute a file of Lisp code named FILE.\n\
First tries FILE with .elc appended, then tries with .el,\n\
then tries FILE unmodified. Searches directories in load-path.\n\
If optional second arg NOERROR is non-nil,\n\
report no error if FILE doesn't exist.\n\
Print messages at start and end of loading unless\n\
optional third arg NOMESSAGE is non-nil.\n\
If optional fourth arg NOSUFFIX is non-nil, don't try adding\n\
suffixes .elc or .el to the specified name FILE.\n\
Return t if file exists.")
(str, noerror, nomessage, nosuffix)
Lisp_Object str, noerror, nomessage, nosuffix;
{
register FILE *stream;
register int fd = -1;
register Lisp_Object lispstream;
register FILE **ptr;
int count = specpdl_ptr - specpdl;
struct gcpro gcpro1;
CHECK_STRING (str, 0);
str = Fsubstitute_in_file_name (str);
/* Avoid weird lossage with null string as arg,
since it would try to load a directory as a Lisp file */
if (XSTRING (str)->size > 0)
{
fd = openp (Vload_path, str, !NULL (nosuffix) ? "" : ".elc:.el:", 0, 0);
}
if (fd < 0)
if (NULL (noerror))
while (1)
Fsignal (Qfile_error, Fcons (build_string ("Cannot open load file"),
Fcons (str, Qnil)));
else return Qnil;
stream = fdopen (fd, "r");
if (stream == 0)
{
close (fd);
error ("Failure to create stdio stream for %s", XSTRING (str)->data);
}
if (NULL (nomessage))
message ("Loading %s...", XSTRING (str)->data);
GCPRO1 (str);
ptr = (FILE **) xmalloc (sizeof (FILE *));
*ptr = stream;
XSET (lispstream, Lisp_Internal_Stream, (int) ptr);
record_unwind_protect (load_unwind, lispstream);
load_in_progress++;
readevalloop (Qget_file_char, stream, Feval, 0);
unbind_to (count);
UNGCPRO;
if (!noninteractive && NULL (nomessage))
message ("Loading %s...done", XSTRING (str)->data);
return Qt;
}
static Lisp_Object
load_unwind (stream) /* used as unwind-protect function in load */
Lisp_Object stream;
{
fclose (*(FILE **) XSTRING (stream));
free (XPNTR (stream));
if (--load_in_progress < 0) load_in_progress = 0;
return Qnil;
}
static int
absolute_filename_p (pathname)
Lisp_Object pathname;
{
register unsigned char *s = XSTRING (pathname)->data;
return (*s == '~' || *s == '/'
/**
** (sjk)++ added || defined(atarist) below
**/
#if defined(VMS) || defined(atarist)
|| index (s, ':')
#endif /* VMS or atarist */
);
}
/* Search for a file whose name is STR, looking in directories
in the Lisp list PATH, and trying suffixes from SUFFIX.
SUFFIX is a string containing possible suffixes separated by colons.
On success, returns a file descriptor. On failure, returns -1.
EXEC_ONLY nonzero means don't open the files,
just look for one that is executable. In this case,
returns 1 on success.
If STOREPTR is nonzero, it points to a slot where the name of
the file actually found should be stored as a Lisp string.
Nil is stored there on failure. */
int
openp (path, str, suffix, storeptr, exec_only)
Lisp_Object path, str;
char *suffix;
Lisp_Object *storeptr;
int exec_only;
{
register int fd;
int fn_size = 100;
char buf[100];
register char *fn = buf;
int absolute = 0;
int want_size;
register Lisp_Object filename;
struct stat st;
if (storeptr)
*storeptr = Qnil;
if (absolute_filename_p (str))
absolute = 1;
for (; !NULL (path); path = Fcdr (path))
{
char *nsuffix;
filename = Fexpand_file_name (str, Fcar (path));
if (!absolute_filename_p (filename))
/* If there are non-absolute elts in PATH (eg ".") */
/* Of course, this could conceivably lose if luser sets
default-directory to be something non-absolute... */
{
filename = Fexpand_file_name (filename, current_buffer->directory);
if (!absolute_filename_p (filename))
/* Give up on this path element! */
continue;
}
/* Calculate maximum size of any filename made from
this path element/specified file name and any possible suffix. */
want_size =